/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.sunspotworld.protocols;

import com.sun.spot.peripheral.ChannelBusyException;
import com.sun.spot.peripheral.NoAckException;
import com.sun.spot.peripheral.radio.IProtocolManager;
import com.sun.spot.peripheral.radio.IRadiogramProtocolManager;
import com.sun.spot.peripheral.radio.LowPan;
import com.sun.spot.peripheral.radio.LowPanHeaderInfo;
import com.sun.spot.peripheral.radio.RadioPacket;
import com.sun.spot.util.IEEEAddress;
import com.sun.spot.util.Utils;
import java.util.Random;
import org.sunspotworld.sensortasks.routingtasks.AdvertiseTask;
import org.sunspotworld.market.MarketAgent;

/**
 *
 * @author me
 */
public class AdvertisementProtocol implements IProtocolManager {
    private static boolean protocolEnabled = false;
    public static final byte PROTOCOL_NUM = MyProtocols.ADVERTISEMENT;
    private byte[] bid = new byte[PAYLOAD_SIZE];
    private int size = 1;
    private int retries = 0;
    
    private static final int PAYLOAD_SIZE = RadioPacket.MIN_PAYLOAD_LENGTH - IRadiogramProtocolManager.DATA_OFFSET;
    
    private static Random random = new Random(new IEEEAddress(System.getProperty("IEEE_ADDRESS")).asLong());
    private static final int RANDOM_BACKOFF = 10;
    private static final int CONSTANT_BACKOFF = 2;
    private static final int BROADCAST_RETRIES = 5;
    
    public static void setEnabled(boolean enabled) {
        protocolEnabled = enabled;
    }
    
    public void processIncomingData(byte[] arg0, LowPanHeaderInfo arg1) {
        AdvertiseTask.setOverheard();
        if (!protocolEnabled) {
            return;
        }
        //reply to advertisement if supply needed
        if (MarketAgent.getInstance().getTotalSupply() < MarketAgent.getInstance().getTotalDemand() + 1) {
            //update advertisement information
            /*nothing to update*/
            //send bid
            sendBid(arg1.sourceAddress);
        }
        setEnabled(false);
        AwardProtocol.setEnabled(true);
        TimeProtocol.processTime(arg0, arg1);
    }
    
    private void sendBid (long address) {
        try {
            LowPan.getInstance().sendWithoutMeshingOrFragmentation(MyProtocols.BID, address, bid, 0, size);
            System.out.println("bid sent");
        } catch (NoAckException ex) {
            if (retries < BROADCAST_RETRIES && protocolEnabled) {  //if retried less than 5 times and still responding to advertisements
                retries++;
                sendBid(address);
            } else {
                ex.printStackTrace();
            }
        } catch (ChannelBusyException ex) {
            if (protocolEnabled) {  //if still responding to advertisements
                //retry if channel busy
                Utils.sleep(random.nextInt(RANDOM_BACKOFF) + CONSTANT_BACKOFF);  // wait a random amount before retrying
                sendBid(address);
            }
        }
        retries = 0;  //retries resets after first recursive call of sendPacket falls through to here
    }
}
